package com.zz.yt.lib.annex;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Environment;
import android.util.Base64;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.EncodeUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ObjectUtils;
import com.whf.android.jar.util.log.LatteLogger;
import com.zz.yt.lib.annex.document.bean.AnnexBean;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;


/**
 * @ClassName BitmapUtils
 * @Description 图片工具类
 * @Author GZL
 * @Date 2024/12/25 9:21
 * @Version 1.0
 **/
public class BitmapUtils {

    /// PEG格式图片的Base64数据URI前缀
    public static final String DATA_JPEG_64 = "data:image/jpeg;base64,";
    /// PNG格式图片的Base64数据URI前缀
    public static final String DATA_PNG_64 = "data:image/png;base64,";

    /**
     * 压缩图片
     *
     * @param context    上下文
     * @param annexBean  图片信息
     * @param isCompress 是否压缩
     * @param reqWidth   宽
     * @param reqHeight  高
     */
    public static AnnexBean compressIMG(Context context, AnnexBean annexBean, boolean isCompress, int reqWidth, int reqHeight) {
        if (!isCompress) {
            // 如果不需要压缩，直接返回原始 AnnexBean
            return annexBean;
        }

        // 获取应用 Pictures 目录下的所有文件列表，用于检查是否已存在压缩过的图片
        List<File> files = FileUtils.listFilesInDir(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));

        // 初始化返回的 AnnexBean 为原始对象
        AnnexBean bean = annexBean;

        // 计算原始图片文件的 MD5 值，用于唯一标识该图片
        String md5 = FileUtils.getFileMD5ToString(annexBean.getPath());

        // 标记是否已经存在压缩过的图片
        boolean flag = false;

        // 遍历文件列表，查找是否有相同 MD5 的文件（即之前已压缩过的图片）
        for (File file : files) {
            if (file.getPath().contains(md5)) {
                flag = true;
                // 如果找到了，就使用已存在的压缩图片创建新的 AnnexBean
                bean = new AnnexBean(annexBean.getId(), annexBean.getFileName(), file.getPath(), annexBean.getValue());
            }
        }

        // 如果没有找到已压缩的图片，则进行压缩处理
        if (!flag) {
            // 调用 transBitmap 方法对图片进行压缩处理
            Bitmap bitmap = transBitmap(annexBean.getPath(), reqWidth, reqHeight);

            // 构造新的存储路径，使用 MD5 和 UUID 确保文件名唯一
            String storagePath = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                    String.format("%s_%s.png", md5, UUID.randomUUID().toString())).getPath();

            // 记录存储路径日志
            LogUtils.d(storagePath);

            // 保存压缩后的图片到指定路径
            if (savePic(bitmap, storagePath)) {
                // 如果保存成功，创建新的 AnnexBean 指向压缩后的图片路径
                bean = new AnnexBean(annexBean.getId(), annexBean.getFileName(), storagePath, annexBean.getValue());
            }
        }

        return bean;
    }

    /**
     * 压缩图片
     *
     * @param context        上下文
     * @param annexBean      图片信息
     * @param isCompress     是否压缩
     * @param reqWidth       宽
     * @param reqHeight      高
     * @param followRotation 是否旋转
     */
    public static AnnexBean compressIMG(Context context, AnnexBean annexBean, boolean isCompress, int reqWidth, int reqHeight, boolean followRotation) {
        if (!isCompress) {
            // 如果不需要压缩，直接返回原始 AnnexBean
            return annexBean;
        }

        // 获取应用 Pictures 目录下的所有文件列表，用于检查是否已存在压缩过的图片
        List<File> files = FileUtils.listFilesInDir(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));

        // 初始化返回的 AnnexBean 为原始对象
        AnnexBean bean = annexBean;

        // 计算原始图片文件的 MD5 值，用于唯一标识该图片
        String md5 = FileUtils.getFileMD5ToString(annexBean.getPath());

        // 标记是否已经存在压缩过的图片
        boolean flag = false;

        // 遍历文件列表，查找是否有相同 MD5 的文件（即之前已压缩过的图片）
        for (File file : files) {
            if (file.getPath().contains(md5)) {
                flag = true;
                // 如果找到了，就使用已存在的压缩图片创建新的 AnnexBean
                bean = new AnnexBean(annexBean.getId(), annexBean.getFileName(), file.getPath(), annexBean.getValue());
            }
        }

        // 如果没有找到已压缩的图片，则进行压缩处理
        if (!flag) {
            // 调用 transBitmap 方法对图片进行压缩处理，考虑旋转方向
            Bitmap bitmap = transBitmap(annexBean.getPath(), reqWidth, reqHeight, followRotation);

            // 构造新的存储路径，使用 MD5 和 UUID 确保文件名唯一
            String storagePath = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                    String.format("%s_%s.png", md5, UUID.randomUUID().toString())).getPath();

            // 记录存储路径日志
            LogUtils.d(storagePath);

            // 保存压缩后的图片到指定路径
            if (savePic(bitmap, storagePath)) {
                // 如果保存成功，创建新的 AnnexBean 指向压缩后的图片路径
                bean = new AnnexBean(annexBean.getId(), annexBean.getFileName(), storagePath, annexBean.getValue());
            }
        }

        return bean;
    }

    /**
     * 压缩图片
     *
     * @param context    上下文
     * @param annexBean  图片信息
     * @param isCompress 是否压缩
     * @param reqWidth   宽
     * @param reqHeight  高
     */
    public static List<String> compressIMG(Context context, List<String> annexBean, boolean isCompress, int reqWidth, int reqHeight) {
        if (!isCompress) {
            // 如果不需要压缩，直接返回原始 AnnexBean
            return annexBean;
        }

        // 获取应用 Pictures 目录下的所有文件列表，用于检查是否已存在压缩过的图片
        List<File> files = FileUtils.listFilesInDir(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));

        // 创建用于存储处理后图片路径的列表
        List<String> fileArray = new ArrayList<>();

        // 遍历输入的图片路径列表
        for (String ar : annexBean) {
            // 计算当前图片文件的MD5值，用于唯一标识和避免重复处理
            String md5 = FileUtils.getFileMD5ToString(ar);

            // 标记是否已存在处理过的图片
            boolean flag = false;

            // 检查是否已经有相同MD5的图片被处理过
            for (File file : files) {
                if (file.getPath().contains(md5)) {
                    flag = true;
                    // 如果已存在，直接添加已处理图片的路径
                    fileArray.add(file.getPath());
                }
            }

            // 如果不存在已处理的图片，则进行压缩处理
            if (!flag) {
                // 调用transBitmap方法对图片进行压缩处理
                Bitmap bitmap = transBitmap(ar, reqWidth, reqHeight);

                // 生成唯一的存储路径，使用MD5和UUID确保文件名不重复
                String storagePath = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                        String.format("%s_%s.png", md5, UUID.randomUUID().toString())).getPath();

                // 记录存储路径日志
                LogUtils.d(storagePath);

                // 保存压缩后的图片到指定路径
                if (savePic(bitmap, storagePath)) {
                    // 保存成功则将新路径添加到结果列表中
                    fileArray.add(storagePath);
                }
            }
        }
        return fileArray;
    }

    /**
     * 压缩图片
     *
     * @param context        上下文
     * @param annexBean      图片信息
     * @param isCompress     是否压缩
     * @param reqWidth       宽
     * @param reqHeight      高
     * @param followRotation 是否旋转
     */
    public static List<String> compressIMG(Context context, List<String> annexBean, boolean isCompress, int reqWidth, int reqHeight, boolean followRotation) {
        if (!isCompress) {
            // 如果不需要压缩，直接返回原始 AnnexBean
            return annexBean;
        }

        // 获取应用 Pictures 目录下的所有文件列表，用于检查是否已存在压缩过的图片
        List<File> files = FileUtils.listFilesInDir(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));

        // 创建用于存储处理后图片路径的列表
        List<String> fileArray = new ArrayList<>();

        // 遍历输入的图片路径列表
        for (String ar : annexBean) {

            // 计算当前图片文件的MD5值，用于唯一标识和避免重复处理
            String md5 = FileUtils.getFileMD5ToString(ar);

            // 标记是否已存在处理过的图片
            boolean flag = false;

            // 检查是否已经有相同MD5的图片被处理过
            for (File file : files) {
                if (file.getPath().contains(md5)) {
                    flag = true;
                    // 如果已存在，直接添加已处理图片的路径
                    fileArray.add(file.getPath());
                }
            }

            // 如果不存在已处理的图片，则进行压缩处理
            if (!flag) {
                // 调用transBitmap方法对图片进行压缩处理
                Bitmap bitmap = transBitmap(ar, reqWidth, reqHeight, followRotation);

                // 生成唯一的存储路径，使用MD5和UUID确保文件名不重复
                String storagePath = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                        String.format("%s_%s.png", md5, UUID.randomUUID().toString())).getPath();

                // 记录存储路径日志
                LogUtils.d(storagePath);

                // 保存压缩后的图片到指定路径
                if (savePic(bitmap, storagePath)) {
                    // 保存成功则将新路径添加到结果列表中
                    fileArray.add(storagePath);
                }
            }
        }
        return fileArray;
    }

    /**
     * 压缩图片
     *
     * @param context    上下文
     * @param annexBean  图片信息
     * @param isCompress 是否压缩
     * @param reqWidth   宽
     * @param reqHeight  高
     */
    public static String compressIMG(Context context, String annexBean, boolean isCompress, int reqWidth, int reqHeight, boolean followRotation) {
        if (!isCompress) {
            // 如果不需要压缩，直接返回原始 AnnexBean
            return annexBean;
        }

        // 获取应用 Pictures 目录下的所有文件列表，用于检查是否已存在压缩过的图片
        List<File> files = FileUtils.listFilesInDir(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));

        String fileArray = "";

        // 计算当前图片文件的MD5值，用于唯一标识和避免重复处理
        String md5 = FileUtils.getFileMD5ToString(annexBean);

        // 标记是否已存在处理过的图片
        boolean flag = false;

        // 检查是否已经有相同MD5的图片被处理过
        for (File file : files) {
            if (file.getPath().contains(md5)) {
                flag = true;
                // 如果已存在，直接添加已处理图片的路径
                fileArray = file.getPath();
            }
        }

        // 如果不存在已处理的图片，则进行压缩处理
        if (!flag) {
            // 调用transBitmap方法对图片进行压缩处理
            Bitmap bitmap = transBitmap(annexBean, reqWidth, reqHeight, followRotation);

            // 生成唯一的存储路径，使用MD5和UUID确保文件名不重复
            String storagePath = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                    String.format("%s_%s.png", md5, UUID.randomUUID().toString())).getPath();

            // 记录存储路径日志
            LogUtils.d(storagePath);

            // 保存压缩后的图片到指定路径
            if (savePic(bitmap, storagePath)) {
                fileArray = storagePath;
            }
        }
        return fileArray;
    }

    /**
     * 指定分辨率和清晰度的图片压缩方法
     *
     * @param reqWidth:
     * @param reqHeight:
     */
    public static Bitmap transImage(Bitmap bitmap, int reqWidth, int reqHeight) {
        if (bitmap == null || bitmap.isRecycled()) {
            return bitmap;
        }
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        // 缩放的尺寸
        int require = Math.min(reqHeight, reqWidth);
        float scale;
        if (reqHeight > reqWidth) {
            scale = (float) require / bitmapWidth;
        } else {
            scale = (float) require / bitmapHeight;
        }
        if (scale >= 1f) {
            return bitmap;
        }
//        Bitmap bitmap1 = Bitmap.createBitmap(reqWidth, reqHeight, Bitmap.Config.ARGB_8888);
//        Canvas canvas = new Canvas(bitmap1);
//        canvas.scale(scale,scale);
//        Paint paint = new Paint();
//        paint.setAntiAlias(true);
//        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
//        canvas.drawBitmap(bitmap,0,0,paint);

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
        // 产生缩放后的Bitmap对象
        Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
//        // 保存到文件
//        bitmap2File(toFile, quality, resizeBitmap);
//        if (!bitmap.isRecycled()) {
//            // 释放资源，以防止OOM
//            bitmap.recycle();
//        }
//        if (!resizeBitmap.isRecycled()) {
//            resizeBitmap.recycle();
//        }
        return resizeBitmap;
    }

    @Nullable
    public static Bitmap transBitmap(String path, int maxWidth, int maxHeight) {
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        if (bitmap == null) {
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        if (width > height && maxWidth < maxHeight) {
            int tmp = maxWidth;
            maxWidth = maxHeight;
            maxHeight = tmp;
        }

        if (width <= maxWidth && height <= maxHeight) {
            return bitmap;
        }
        return transImage(bitmap, maxWidth, maxHeight);
    }

    @Nullable
    public static Bitmap transBitmap(String path, int maxWidth, int maxHeight, boolean followRotation) {
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        if (bitmap == null) {
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        if (followRotation && width > height && maxWidth < maxHeight) {
            int tmp = maxWidth;
            maxWidth = maxHeight;
            maxHeight = tmp;
        }

        if (width <= maxWidth && height <= maxHeight) {
            return bitmap;
        }
        return transImage(bitmap, maxWidth, maxHeight);

    }

    /**
     * Bitmap转换为文件
     *
     * @param toFile:
     * @param quality:
     * @param bitmap:
     */
    @NonNull
    public static File bitmap2File(String toFile, int quality, @NonNull Bitmap bitmap) {
        File captureFile = new File(toFile);
        FileOutputStream out;
        try {
            out = new FileOutputStream(captureFile);
            if (bitmap.compress(Bitmap.CompressFormat.PNG, quality, out)) {
                out.flush();
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return captureFile;
    }

    /**
     * @param reqWidth:
     * @param reqHeight:
     */
    public static Bitmap transSide(Bitmap bitmap, int reqWidth, int reqHeight) {
        if (bitmap == null || bitmap.isRecycled()) {
            return bitmap;
        }
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        // 缩放的尺寸
        float scale;
        //原图宽高比
        float bitmapScale = (float) bitmapWidth / (float) bitmapHeight;
        //先假定以width缩放，计算出height
        float b_height = reqWidth / bitmapScale;
        if (b_height >= reqHeight) {
            //如果计算出来的height大于等于遮罩width，则以width缩放
            scale = reqWidth * 1f / bitmapWidth;
        } else {
            //反之，则以Height缩放
            scale = reqHeight * 1f / bitmapHeight;
        }
        if (scale == 1f) {
            return bitmap;
        }
        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
        // 产生缩放后的Bitmap对象
        return Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
    }

    /**
     * @param pBitmap:保存图片到sdcard中
     */
    public static boolean savePic(Bitmap pBitmap, String strName) {
        if (pBitmap == null) {
            return false;
        }
        FileOutputStream fos = null;
        try {
            File file = new File(strName);
            if (file.exists()) {
                file.delete();
            }
            if (!Objects.requireNonNull(file.getParentFile()).exists()) {
                file.mkdirs();
            }
            fos = new FileOutputStream(strName);
            pBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
            return true;

        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
        return false;
    }

    /**
     * @param path:将图片转换为Bitmap对象
     */
    public static Bitmap path2Bitmap(String path) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        return BitmapFactory.decodeFile(path, options);
    }

    /**
     * @param bitmap: 将Bitmap对象转换为字节数组
     */
    @NonNull
    public static byte[] bitmap2Bytes(Bitmap bitmap) {
        if (bitmap == null) {
            return new byte[1024];
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * @param bitmap: 将Bitmap对象转换为字节数组,使用Base64编码
     */
    @NonNull
    public static String bitmap2Base64(Bitmap bitmap) {
        if (bitmap == null) {
            return "";
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        return DATA_PNG_64 + Base64.encodeToString(bytes, Base64.DEFAULT);
    }

    /**
     * @param base64:Base64图片转换为Bitmap对象
     */
    @Nullable
    public static Bitmap base642Bitmap(String base64) {
        if (ObjectUtils.isEmpty(base64)) {
            return null;
        }
        Bitmap mBitmap = null;
        try {
            String data = base64.replace(DATA_JPEG_64, "")
                    .replace(DATA_PNG_64, "");
            byte[] bytes = EncodeUtils.base64Decode(data);
            mBitmap = ConvertUtils.bytes2Bitmap(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (mBitmap == null) {
            LatteLogger.e("图片转换出错");
        }
        return null;
    }


}
